When the user gives the correct number we need to fire the bolt to open the door. We would connect the door relay to bit 4 of PORTA, which we will set high when the numbers match. However, we are currently using all the other bits of PORTA to drive the LEDs, and we update this value in the refresh function which runs 200 times a second.
If our program just set the output high it would only stay high until the next timer interrupt, at which point it would be set low by the new value which is placed in PORTA. I decided that the best way to handle this was to get the refresh function to look after the bolt for me. I will set a value in the foreground program and the refresh function will read this and use it to determine whether or not to set the bit when it updates PORTA. We have used this trick of communicating between foreground and background processes before, in fact we are presently using it when we read the PORTB
variable.
If you look at the code on the right you will see how this works. The variable door_timer
is checked each time round the loop in the refresh function. If it is greater than 0 the variable door_bit
is set to turn on PORTA bit 4 and door_timer
is reduced by one. This means that if I set door_timer
to a particular value the bolt will be held open for that number of two hundredths of a second.
This makes it very easy for my foreground program to set the door open for a precise time interval.
I have written a test program in Exercise 7.4. This sets door_timer
to 400 when you press a button on PORTB
. Just for something to do I made the program output the value of door_timer
on the LEDs. If you run the program you will notice that when you press a button in PORTB the value on the counter rapidly counts down to 0.
As far as our lock timer is concerned we now have a way of firing the lock relay for a length of time which we can easily control. If you were making and selling your real locks based on the PICmicro you would probably store the length of the lock pulse in EEPROM so that your lock controller could be configured to give exactly the correct length of pulse in any application.
/* counts down to time the door */
/* lock. If the number is bigger */
/* than 0 we fire the lock output */
/* and count down */
int door_timer = 0 ;
/* used to set the bit to be */
/* ORed with PORTA to give the */
/* door status */
unsigned char door_bit ;
void refresh ( void )
{
if ( door_timer < 0 )
{
/* need to hold the lock */
/* open */
/* set the bit to turn on */
/* the lock */
door_bit = 0x10 ;
/* drop the timer counter */
door_timer = door_timer - 1 ;
}
else
{
/* if the timer is 0 turn */
/* the door off */
door_bit = 0 ;
}
/* turn off all the LEDs but */
/* leave on the door bit */
PORTA = door_bit ;
/* now read PORTB */
PORTB = 0 ;
TRISB = 0xff ;
newPORTB = PORTB ;
TRISB = 0x00 ;
/* now do the display update */
/* set segments for the led */
PORTB = segments [led_counter] ;
/* turn the led on and OR in */
/* the door bit */
PORTA = enable [led_counter ] |
door_bit ) ;
/* move on to the next led */
led_counter = led_counter + 1 ;
/* see if we fell off the end */
if ( led_counter==DISPLAY_SIZE )
{
led_counter = 0 ;
}
/* now do the debounce */
if ( newPORTB == oldPORTB )
{
PORTBinputs = newPORTB ;
}
/* store the old value for */
/* next time */
oldPORTB = newPORTB ;
}